package cn.kent;

import org.junit.Test;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 方法引用：
 * 1. 使用情景：当要传递给Lambda体的操作，已经有实现的方法了，可以使用方法引用！
 * 2. 方法引用，本质上就是Lambda表达式，而Lambda表达式作为函数式接口的实例，所以
 * 方法引用也是函数式接口的实例。
 * 3. 使用格式: 类（或对象） :: 方法名
 * 4. 分为以下三种情况：
 * 对象::非静态方法
 * 类::静态方法
 * 类::非静态方法
 * 5. 方法引用的要求：要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同
 */
public class MethodReferenceTest {

    /**
     * 对象::非静态方法
     */
    @Test
    public void test01() {
        Consumer<String> c = str -> System.out.println(str);
        c.accept("中国红");

        PrintStream ps = System.out;
        Consumer<String> consumer = ps::println;
        consumer.accept("北京红");
    }

    /**
     * 类::静态方法
     */
    @Test
    public void test2() {
        Comparator<Integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
        System.out.println(comparator.compare(12, 21));

        Comparator<Integer> comparator1 = Integer::compare;
        System.out.println(comparator1.compare(12, 21));
    }

    /**
     * 类::静态方法
     */
    @Test
    public void test3() {
        Function<Double, Long> func = new Function<Double, Long>() {
            @Override
            public Long apply(Double d) {
                return Math.round(d);
            }
        };

        Function<Double, Long> func1 = d -> Math.round(d);

        Function<Double, Long> func2 = Math::round;

        System.out.println(func.apply(-12.03D));
    }

    /**
     * 类::实例方法 (有难度)
     * Comparator.compare(T t1, T t2)
     * String中的 int t1.compareTo(t2)
     */
    @Test
    public void test4() {
        Comparator<String> com1 = (t1, t2) -> t1.compareTo(t2);
        System.out.println(com1.compare("abc", "abd"));


        Comparator<String> com2 = String::compareTo;
        System.out.println(com2.compare("abc", "abd"));
    }

    /**
     * 类::实例方法
     */
    @Test
    public void test5() {
        BiPredicate<String, String> predicate = (s1, s2) -> s1.equals(s2);

        BiPredicate<String, String> predicate2 = String::equals;

        System.out.println(predicate.test("abd", "abc"));
    }

}
